#include "c_list.h"

ListNode* ConstructListNode()
{
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	node->data = NULL;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

void DestructListNode(ListNode* node)
{
	if(!node) return ;
	node->next = NULL;
	node->prev = NULL;
	free((void*)node);
	node = NULL;
}

List* ConstructList()
{
	List* ls = (List*)malloc(sizeof(List));
	ListNode* empty_node = ConstructListNode();
	ls->head = empty_node;
	ls->head->next = ls->head;
	ls->head->prev = ls->head;
	return ls;
}

void DestructList(List* ls)
{
	if(!ls || !ls->head) return ;
	free((void*)ls->head);
	ls->head = NULL;
	free((void*)ls);
	ls = NULL;
}

bool InitList(List* ls)
{
	if(!ls) return false;
	ListNode* empty_node = ConstructListNode();
	ls->head = empty_node;
	ls->head->next = ls->head;
	ls->head->prev = ls->head;
	return true;
}

void ReleaseList(List* ls)
{
	if(!ls || !ls->head) return ;
	DestructListNode(ls->head);
}

bool ExistNode(List* ls,ListNode* node)
{
	if(!ls || !node || !ls->head || ls->head->next == ls->head) return false;
	ListNode* cur = ls->head->next;
	while(cur && cur != ls->head)
	{
		if(cur == node) return true;
		cur = cur->next;
	}
	return false;
}

void PushFront(List* ls,void* data)
{
	if(!ls || !data || !ls->head) return ;
    ListNode* node = (ListNode*)malloc(sizeof(ListNode*));
    node->data = data;

	ListNode* tmp = ls->head->next;
	ls->head->next = node;
	node->prev = ls->head;
	node->next = tmp;
	tmp->prev = node;
}

void PushBack(List* ls,void* data)
{
	if(!ls || !data || !ls->head) return ;
    ListNode* node = (ListNode*)malloc(sizeof(ListNode*));
    node->data = data;

	ListNode* rear = ls->head->prev;
	rear->next = node;
	node->prev = rear;
	node->next = ls->head;
	ls->head->prev = node;
}

void Push(List* ls,ListNode* pos,void* data)
{
	if(!ls || !data || !ls->head || !pos || !ExistNode(ls,pos)) return;
    ListNode* node = (ListNode*)malloc(sizeof(ListNode*));
    node->data = data;

	ListNode* tmp = pos->next;
	pos->next = node;
	node->prev = pos;
	node->next = tmp;
	tmp->prev = node;
}

void PopFront(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return;
	ListNode* node = ls->head->next;
	ls->head->next = node->next;
	node->next->prev = ls->head;
    DestructListNode(node);
}

void PopBack(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return;
	ListNode* rear = ls->head->prev;
	rear->prev->next = ls->head;
	ls->head->prev = rear->prev;
    DestructListNode(rear);
}

void* Front(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return NULL;
	return ls->head->next->data;
}

void* Back(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return NULL;
	return ls->head->prev->data;
}

ListNode* Begin(List* ls)
{
	if(!ls || !ls->head) return NULL;
	return ls->head->next;
}

ListNode* End(List* ls)
{
	if(!ls || !ls->head) return NULL;
	return ls->head;
}

ListNode* RBegin(List* ls)
{
	if(!ls || !ls->head) return NULL;
	return ls->head->prev;
}

ListNode* REnd(List* ls)
{
	if(!ls || !ls->head) return NULL;
	return ls->head;
}

bool Empty(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return true;
	return false;
}

unsigned int Length(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return 0;
	unsigned int len = 0;
	for(ListNode* cur=Begin(ls);cur != End(ls); cur=cur->next,++len);
	return len;
}

void Clear(List* ls)
{
	if(!ls || !ls->head || ls->head->next == ls->head) return ;
	ls->head->next = ls->head;
	ls->head->prev = ls->head;
}
